<?php
/**
 * This file is lil-wide controller file. 
 *
 * @copyright     Copyright 2008-2010, LilCake.net
 * @link          http://lilcake.net LilCake.net
 * @package       lil
 * @subpackage    lil
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 */
/**
 * LilAppController class
 *
 * @uses          AppController
 * @package       lil
 * @subpackage    lil
 */
class LilAppController extends AppController {
/**
 * components property
 *
 * @var array
 * @access public
 */
	var $components = array('Session', 'Auth', 'Cookie');
/**
 * helpers property
 *
 * @var array
 * @access public
 */
	var $helpers = array('Session', 'Form', 'Html', 'Text', 'Time', 'Number', 'Lil.Lil');
/**
 * view property
 *
 * @var string
 * @access public
 */
	var $view = 'LilApp';
/**
 * hasData property
 *
 * @var bool
 * @access public
 */
	var $hasData = false;
/**
 * __construct method
 *
 * @access private
 * @return void
 */
	function __construct() {
		
		App::import('Lib', 'Lil.LilPluginRegistry');
		
		// do other plugins
		$plugins = Configure::read('Lil.plugins');	$i=1;
		foreach ((array)$plugins as $plugin) {
			$this->__initPlugin('Lil' . $plugin);
		}
		
		// try to init app plugin after other plugins so app plugin can modify others
		$this->__initPlugin();
		
		$this->callPluginHandlers('before_construct_controller');
		parent::__construct();
		$this->callPluginHandlers('after_construct_controller');
	}
/**
 * __initPlugin method
 *
 * @access private
 * @return void
 */
	function __initPlugin($plugin_name = null) {
		if (!empty($plugin_name)) {
			$import_name = $plugin_name . '.' . $plugin_name . 'Plugin';
			$controller_name = $plugin_name . 'PluginController';
		} else {
			// this is app controller plugin
			$import_name = 'AppPlugin';
			$controller_name = 'AppPluginController';
			$plugin_name = null;
		}
		
		if (App::import('Controller', $import_name)) {
			if ($plugin = new $controller_name()) {
				$plugin->constructClasses();
				$plugin->beforeFilter();
				$plugin->Component->initialize($plugin);
				$plugin->Component->startup($plugin);
				
				// have to set this manually so finding view paths work (Email component)
				if (!empty($plugin_name)) {
					$plugin->plugin = Inflector::underscore($plugin_name);
					$real_plugin_name = $plugin_name;
				} else {
					$real_plugin_name = 'App';
				}
				
				LilPluginRegistry::addObject(Inflector::underscore($real_plugin_name), $plugin);
			}
		}
	}
/**
 * beforeFilter method
 *
 * @access public
 * @return void
 */
	function beforeFilter() {
		if ($lang = $this->Cookie->read('Lil.lang')) {
			if (in_array($lang, Configure::read('Lil.languages'))) Configure::write('Config.language', $lang);
		}
			
		require_once(dirname(__FILE__) . DS . 'lil_app_view.php');
		parent::beforeFilter();
		
		// set area_id
		if (!empty($this->params['admin'])) {
			// set from session if not in params
			if (!empty($this->params['named']['area_id'])) {
				$this->setAdminAreaId($this->params['named']['area_id']);
			} else if (!empty($this->params['named']['area'])) {
				$this->setAdminAreaSlug($this->params['named']['area']);
			} else if ($defArea = Configure::read('Lil.defaultArea')) {
				$this->setAdminAreaSlug($defArea);
			}
		} else if ($this->params['controller'] == 'users' && $this->params['action'] == 'login') {
			$this->Session->delete('admin.area');
		}
		
		Configure::write('Lil.authSessionKey', $this->Auth->sessionKey);
		Configure::write('Lil.authModel', $this->Auth->userModel);
		Configure::write('Lil.authFields', $this->Auth->fields);
		
		$this->callPluginHandlers('before_filter');
		$this->callPluginHandlers('before_' . $this->params['controller'] . '_' . $this->params['action']);
	}
/**
 * afterFilter method
 *
 * @access public
 * @return void
 */
	function afterFilter() {
		parent::afterFilter();

		$this->callPluginHandlers('after_filter');
	}
/**
 * setAdminAreaSlug method
 *
 * This functions sets area id which is used as selected area in administration.
 *
 * @param string $id
 * @access public
 * @return void
 */
	function setAdminAreaSlug($id) {
		if ($areas = Configure::read('Lil.noAreas')) {
			foreach ($areas as $k => $a) {
				if (!empty($a['Area']['slug']) && $a['Area']['slug'] == $id) {
					$this->Session->write('admin.area', $a);
					return true;
				} else if ($k == $id) {
					$this->Session->write('admin.area', $a);
					return true;
				}
			}
			return false;
		} else {
			$Area =& ClassRegistry::init('Lil.Area');
			$Area->recursive = -1;
			if ($data = $Area->find('first', array('conditions' => array('Area.' . Configure::read('Lil.areaSlugField') => $id)))) {
				$this->Session->write('admin.area', $data);
				return true;
			} else return false;
		}
	}
/**
 * setAdminAreaId method
 *
 * This functions sets area id which is used as selected area in administration.
 *
 * @param string $id
 * @access public
 * @return void
 */
	function setAdminAreaId($id) {
		if ($areas = Configure::read('Lil.noAreas')) {
			foreach ($areas as $a) {
				if ($a['Area']['id'] == $id) {
					$this->Session->write('admin.area', $a);
					return true;
				}
			}
			return false;
		} else {
			$Area =& ClassRegistry::init('Lil.Area');
			$Area->recursive = -1;
			if ($data = $Area->read(null, $id)) {
				$this->Session->write('admin.area', $data);
				return true;
			} else return false;
		}
	}
/**
 * clearAdminArea method
 *
 * This functions clears admin area.
 *
 * @access public
 * @return void
 */
	function clearAdminArea() {
		$this->Session->delete('admin.area');
	}
/**
 * getAdminAreaId method
 *
 * This functions returns current area id in administration.
 *
 * @access public
 * @return int
 */
	function getAdminAreaId() {
		if ($data = $this->getAdminArea()) {
			return $data['Area']['id'];
		} else return null;
	}
/**
 * getAdminAreaSlug method
 *
 * This functions returns current area slug in administration.
 *
 * @access public
 * @return int
 */
	function getAdminAreaSlug() {
		if ($data = $this->getAdminArea()) {
			return $data['Area'][Configure::read('Lil.areaSlugField')];
		} else return null;
	}
/**
 * getAdminArea method
 *
 * This functions returns current area in administration.
 *
 * @access public
 * @return array
 */
	function getAdminArea() {
		if (!empty($this->Session) && ($a = $this->Session->read('admin.area'))) {
			return $a;
		} else {
			return null;
		}
	}
/**
 * beforeRender method
 *
 * @access public
 * @return void
 */
	function beforeRender() {
		$this->set('admin_area', $this->getAdminArea());
		
		// read default sidebar and allow plugins to modify it
		// construct sidebar
		$sidebar = array(
			'welcome' => array(
				'visible' => true,
				'items'   => array(
					'dashboard' => array(
						'visible' => true,
						'title' => sprintf(__d('lil', 'Welcome, %s', true), $this->Auth->user(Configure::read('Lil.userDisplayField'))),
						'url'   => array(
							'plugin'     => 'lil',
							'controller' => 'areas',
							'action'     => 'dashboard',
							'admin'      => true,
						),
						'params' => array(),
						'active' =>
							($this->params['controller'] == 'areas' && 
							in_array($this->params['action'], array('admin_dashboard', 'admin_list')))
							||
							($this->params['controller'] == 'users' && 
							in_array($this->params['action'], array('admin_properties')))
							,
						'expand' => 
							($this->params['controller'] == 'areas' && 
							in_array($this->params['action'], array('admin_dashboard', 'admin_list')))
							||
							($this->params['controller'] == 'users' && 
							in_array($this->params['action'], array('admin_properties')))
							,
						'submenu' => array(
							'dashboard' => array(
								'visible' => true,
								'title' => __d('lil', 'Dashboard', true),
								'url'   => array(
									'plugin'     => 'lil',
									'controller' => 'areas',
									'action'     => 'dashboard',
									'admin'      => true,
								),
								'params' => array(),
								'active' =>
									$this->params['controller'] == 'areas' &&
									$this->params['action'] == 'admin_dashboard'
							),
							'area' => array(
								'visible' => true,
								'title' => __d('lil', 'Change admin area', true),
								'url'   => array(
									'plugin'     => 'lil',
									'controller' => 'areas',
									'action'     => 'list',
									'admin'      => true,
								),
								'params' => array(),
								'active' =>
									$this->params['controller'] == 'areas' &&
									$this->params['action'] == 'admin_list'
							),
							'properties' => array(
								'visible' => true,
								'title' => __d('lil', 'Edit user profile', true),
								'url'   => array(
									'plugin'     => 'lil',
									'controller' => 'users',
									'action'     => 'admin_properties',
									'admin'      => true,
								),
								'params' => array(),
								'active' =>
									$this->params['controller'] == 'users' &&
									$this->params['action'] == 'admin_properties'
							),
							'logout' => array(
								'visible' => true,
								'title' => __d('lil', 'Logout', true),
								'url'   => array(
									'plugin'     => 'lil',
									'controller' => 'users',
									'action'     => 'logout',
									'admin'      => false,
								),
								'params' => array(),
								'active' => false
							),
						)
					)
				)
			),
			'admin' => array(
				'visible' => (boolean)$this->Auth->user() &&
					(Configure::read('Lil.allowUsersAnything') ||
					$this->Auth->user(Configure::read('Lil.userAdminField'))),
				'items' => array(
					'users' => array(
						'visible' => true,
						'title' => __d('lil', 'Users', true),
						'url'   => array(
							'plugin'     => 'lil',
							'controller' => 'users',
							'action'     => 'index',
							'admin'      => true,
						),
						'params' => array(),
						'active' => in_array($this->params['controller'], array('users')) &&
							in_array($this->params['action'], array('admin_index', 'admin_edit', 'admin_add')),
						'expand' => in_array($this->params['controller'], array('users')) &&
							in_array($this->params['action'], array('admin_index', 'admin_edit', 'admin_add')),
						'submenu' => array(
							'edit' => array(
								'visible' => true,
								'title' => __d('lil', 'Edit', true),
								'url'   => array(
									'plugin'     => 'lil',
									'controller' => 'users',
									'action'     => 'index',
									'admin'      => true,
								),
								'params' => array(),
								'active' =>
									$this->params['controller'] == 'users' &&
									in_array($this->params['action'], array('admin_edit', 'admin_index'))
							),
							'add' => array(
								'visible' => true,
								'title' => __d('lil', 'Add New', true),
								'url'   => array(
									'plugin'     => 'lil',
									'controller' => 'users',
									'action'     => 'add',
									'admin'      => true,
								),
								'params' => array(),
								'active' =>
									($this->params['controller']=='users') &&
									($this->params['action'] == 'admin_add')
							),
						)
					),
					'areas' => array(
						'visible' => true,
						'title' => __d('lil', 'Areas', true),
						'url'   => array(
							'admin'      => true,
							'plugin'     => 'lil',
							'controller' => 'areas',
							'action'     => 'index',
						),
						'params' => array(),
						'active' => in_array($this->params['controller'], array('areas')) &&
							in_array($this->params['action'], array('admin_index', 'admin_edit', 'admin_add')),
						'expand' => in_array($this->params['controller'], array('areas')) &&
							in_array($this->params['action'], array('admin_index', 'admin_edit', 'admin_add')),
						'submenu' => array(
							'edit' => array(
								'visible' => true,
								'title' => __d('lil', 'Edit', true),
								'url'   => array(
									'plugin'     => 'lil',
									'controller' => 'areas',
									'action'     => 'index',
									'admin'      => true,
								),
								'params' => array(),
								'active' =>
									$this->params['controller'] == 'areas' &&
									in_array($this->params['action'], array('admin_edit', 'admin_index'))
							),
							'add' => array(
								'visible' => true,
								'title' => __d('lil', 'Add New', true),
								'url'   => array(
									'plugin'     => 'lil',
									'controller' => 'areas',
									'action'     => 'add',
									'admin'      => true,
								),
								'params' => array(),
								'active' =>
									($this->params['controller']=='areas') &&
									($this->params['action'] == 'admin_add')
							),
						)
					)
				) // end if items
			),
		);
		$sidebar = $this->callPluginHandlers('admin_sidebar', $sidebar);
		$this->set('admin_sidebar', $sidebar);
		
		// set admin layout
		if(
			!empty($this->params['admin']) && 
			($this->layout == 'default') &&
			($useLayout = Configure::read('Lil.useAdminLayout'))
		) {
			if (is_string($useLayout)) {
				$this->layout = $useLayout;
			} else {
				$this->layout = 'lil_admin';
			}
		}
		parent::beforeRender();
		$this->callPluginHandlers('before_render');
	}
/**
 * isAuthorized method
 *
 * @access public
 * @return void
 */
	function isAuthorized() {
		return $this->callPluginHandlers('isAuthorizedController', true);
	}
/**
 * redirect function
 *
 * @param string $url
 * @param integer $status
 * @param boolean $exit
 * @param boolean $redirectOnAjax
 * @access public
 * @return string
 */
	function redirect($url, $status = null, $exit = true, $redirectOnAjax = false) {
		if (!isset($this->RequestHandler) || !$this->RequestHandler->isAjax() || $redirectOnAjax) {
			parent::redirect($url, $status, $exit);
		} else {
			$this->autoRender = false;
			$html = $this->render('popups' . DS . $this->action);
		}
	}
/**
 * doRedirect function
 *
 * @param string $fallback_url
 * @access public
 * @return string
 */
	function doRedirect($fallback_url = array(), $override = false) {
		$referer = '?';
		if (!empty($this->data[$this->modelClass]['referer'])) {
			$referer = base64_decode($this->data[$this->modelClass]['referer']);
		}
		
		if ($referer != '?' && !$override) {
			$this->redirect($referer);
		} else if (!empty($fallback_url)) {
			$this->redirect((array)$fallback_url);
		} else {
			$this->redirect(array('action' => 'index'));
		}
	}
/**
 * setupRedirect function
 *
 * @access public
 * @return string
 */
	function setupRedirect() {
		if (empty($this->data[$this->modelClass]['referer'])) {
			$this->data[$this->modelClass]['referer'] = base64_encode($this->referer('?'));
		}
	}
/**
 * parseUrl function
 *
 * @param string $url
 * @access public
 * @return string
 */
	function parseUrl($url) {
		$url = Router::parse($url);
		
		$qs = $this->params['url'];
		unset($qs['url']); unset($qs['ext']);
		if (!empty($qs)) $qs = array('?' => $qs);
		
		$url = array_merge($url, $url['named'], $url['pass'], $qs);
		
		unset($url['named']); unset($url['pass']); unset($url['url']);
		return $url;
	}
/**
 * error404 function
 *
 * @access public
 * @return void
 */
	function error404() {
		$this->cakeError('error404', array());
	}
/**
 * setFlash function
 *
 * @param string $message
 * @param string $layout
 * @param boolean $flashOnAjax
 * @access public
 * @return void
 */
	function setFlash($message, $element = 'default', $flashOnAjax = false) {
		if (!isset($this->RequestHandler) || !$this->RequestHandler->isAjax() || $flashOnAjax) {
			$this->Session->setFlash($message, $element);
		}
	}
/**
 * callPluginHandlers method
 *
 * @param string $handler
 * @access public
 * @return void
 */
	function callPluginHandlers($handler, $args = null) {
		// execute plugin handlers
		$ret = $args;
		
		$plugins = LilPluginRegistry::keys();
		foreach ((array)$plugins as $plugin_key) {
			$plugin = LilPluginRegistry::getObject($plugin_key);
			if (
				!empty($plugin->handlers[$handler]) &&
				method_exists($plugin, $plugin->handlers[$handler]['function'])
			)
			{
				$ret = call_user_func_array(
					array($plugin, $plugin->handlers[$handler]['function']),
					array(
						'controller'  => $this,
						'args'   => (array)$ret,
						'params' => (array)$plugin->handlers[$handler]['params'],
					)
				);
			}
		}
		return $ret;
	}
/**
 * user method
 *
 * Returns current user
 *
 * @param mixed $key
 * @access public
 * @return mixed
 */
	function user($key = null) {
		static $session = null;
		if (empty($session)) $session = new CakeSession();
		
		if ($session->valid(Configure::read('Lil.authSessionKey'))) {
			if ($key == null) {
				return array(
					Configure::read('Lil.authModel') => 
						$session->read(Configure::read('Lil.authSessionKey'))
				);
			} else {
				$user = $session->read(Configure::read('Lil.authSessionKey'));
				if (isset($user[$key])) return $user[$key];
			}
		}
		return null;
	}
/**
 * isAdmin method
 *
 * Returns user is an administrator. 
 * If there is no user specified, current user admin status is returned.
 *
 * @param mixed $user_id
 * @access public
 * @return mixed
 */
	function isAdmin($user_id = null) {
		if (empty($user_id) || ($user_id == $this->user('id'))) {
			static $session = null;
			if (empty($session)) $session = new CakeSession();
			
			if ($session->valid(Configure::read('Lil.authSessionKey')) &&
				$user = $session->read(Configure::read('Lil.authSessionKey')))
			{
				return (bool)$user[Configure::read('Lil.userAdminField')];
			}
			return false;
		} else {
			$User =& ClassRegistry::init('Lil.User');
			return (bool)$User->field(
				Configure::read('Lil.userAdminField'),
				array('User.id' => $user_id)
			);
		}
	}
}
?>